<?php

declare(strict_types=1);

namespace App\Service;

use App\Constants\XZXResponseCode;
use App\Exception\XZXValidationException;
use App\Model\Dao\CommissionSalesDao;
use App\Model\Dao\StatMonthlyChannelDao;
use App\Model\Dao\StatMonthlyTradeChannelDao;
use App\Model\Dao\StatMonthlyTradeDao;
use App\Utils\CustomUtils;
use App\Utils\DateUtils;
use App\Utils\NumberUtils;
use Hyperf\DbConnection\Db;
use Hyperf\Di\Annotation\Inject;

//* 通用service
class StatMonthlyTradeService
{

    /**
     * @Inject()
     * @var StatMonthlyTradeDao
     */
    private $StatMonthlyTradeDao;

    /**
     * @Inject()
     * @var StatMonthlyChannelDao
     */
    private $StatMonthlyChannelDao;

    /**
     * @Inject()
     * @var StatMonthlyTradeChannelDao
     */
    private $StatMonthlyTradeChannelDao;

    /**
     * @Inject()
     * @var CommissionSalesDao
     */
    private $CommissionSalesDao;

    public function statMchList(array $param)
    {
        $limit = $param['limit'];
        $page = $param['page'];

        $total = $this->StatMonthlyTradeDao->getStatCount($param);
        $list = $this->StatMonthlyTradeDao->getStatList($param, $page, $limit);

        foreach ($list as $k => $v) {
            (isset($v['createTime']) && !empty($v['createTime'])) && $v['createTime'] = DateUtils::getDateTime($v['createTime']);
            $v['floatSuccessRate']         = NumberUtils::formatRate($v['successRate']);
            $v['floatRefundRate']          = NumberUtils::formatRate($v['refundRate']);
            $v['floatDisRate']             = NumberUtils::formatRate($v['disRate']);
            $v['floatSuccessSettleAmount'] = sprintf('%.2f', $v['successSettleAmount'] / 100);
            $list[$k] = $v;
        }

        $data = array(
            'total' => $total,
            'list' => $list
        );

        return CustomUtils::xeServiceReturnData(XZXResponseCode::SUCCESS_CODE,XZXResponseCode::getMessage(XZXResponseCode::SUCCESS_CODE),$data);
    }

    public function statChannelList(array $param) {
        $limit = $param['limit'];
        $page = $param['page'];

        $total = $this->StatMonthlyChannelDao->getStatCount($param);
        $list = $this->StatMonthlyChannelDao->getStatList($param, $page, $limit);

        foreach ($list as $k => $v) {
            (isset($v['createTime']) && !empty($v['createTime'])) && $v['createTime'] = DateUtils::getDateTime($v['createTime']);
            $v['floatSuccessRate'] = NumberUtils::formatRate($v['successRate']);
            $v['floatRefundRate']  = NumberUtils::formatRate($v['refundRate']);
            $v['floatDisRate']     = NumberUtils::formatRate($v['disRate']);
            $list[$k] = $v;
        }
        $data = array(
            'total' => $total,
            'list' => $list
        );

        return CustomUtils::xeServiceReturnData(XZXResponseCode::SUCCESS_CODE,XZXResponseCode::getMessage(XZXResponseCode::SUCCESS_CODE),$data);
    }

    public function financeMchList(array $param)
    {

        $limit = $param['limit'];
        $page = $param['page'];

        $total = $this->StatMonthlyTradeDao->getStatCount($param);
        $list = $this->StatMonthlyTradeDao->getFinanceList($param, $page, $limit);

        foreach ($list as $k => $v) {
            (isset($v['createTime']) && !empty($v['createTime'])) && $v['createTime'] = DateUtils::getDateTime($v['createTime']);

            $v['floatSuccessSettleAmount']  = NumberUtils::centToYuan($v['successSettleAmount']);
            $v['floatDisSettleAmount']      = NumberUtils::centToYuan($v['disSettleAmount']);
            $v['floatRefundSettleAmount']   = NumberUtils::centToYuan($v['refundSettleAmount']);
            $v['floatSettleAmount']         = NumberUtils::centToYuan($v['settleAmount']);
            $v['floatServiceFee']           = NumberUtils::centToYuan($v['serviceFee']);
            $v['floatPerFee']               = NumberUtils::centToYuan($v['perFee']);
            $v['floatFrozenSettleAmount']   = NumberUtils::centToYuan($v['frozenSettleAmount']);
            $v['floatThawSettleAmount']     = NumberUtils::centToYuan($v['thawSettleAmount']);
            $v['floatBondAmount']           = NumberUtils::centToYuan($v['bondAmount']);
            $v['floatWithdrawFee']          = NumberUtils::centToYuan($v['withdrawFee']);
            $v['floatTransFee']             = NumberUtils::centToYuan($v['transFee']);
            $v['floatRefundFee']            = NumberUtils::centToYuan($v['refundFee']);
            $v['floatDisFee']               = NumberUtils::centToYuan($v['disFee']);
            $v['floatDisLookIntoFee']       = NumberUtils::centToYuan($v['disLookIntoFee']);
            $v['floatThreeDJudgeFee']       = NumberUtils::centToYuan($v['threeDJudgeFee']);
            $v['floatThreeDFee']            = NumberUtils::centToYuan($v['threeDFee']);

            $v['salesCommission']           = $v['salesCommission1'] + $v['salesCommission2'];
            $v['floatSalesCommission']      = NumberUtils::centToYuan($v['salesCommission']);
            $v['floatEventFreezeAmount']    = NumberUtils::centToYuan($v['eventFreezeAmount']);
            $v['floatEventThawAmount']      = NumberUtils::centToYuan($v['eventThawAmount']);
            $v['floatEventDeductionAmount'] = NumberUtils::centToYuan($v['eventDeductionAmount']);
            $v['floatEventRechargeAmount']  = NumberUtils::centToYuan($v['eventRechargeAmount']);

            $list[$k] = $v;
        }

        $data = array(
            'total' => $total,
            'list' => $list
        );

        return CustomUtils::xeServiceReturnData(XZXResponseCode::SUCCESS_CODE,XZXResponseCode::getMessage(XZXResponseCode::SUCCESS_CODE),$data);
    }

    public function financeChannelList(array $param) {
        $limit = $param['limit'];
        $page = $param['page'];

        $total = $this->StatMonthlyChannelDao->getStatCount($param);
        $list = $this->StatMonthlyChannelDao->getFinanceList($param, $page, $limit);

        foreach ($list as $k => $v) {
            (isset($v['createTime']) && !empty($v['createTime'])) && $v['createTime'] = DateUtils::getDateTime($v['createTime']);
            $v['currencyTransSalesCommission'] = $v['currencyTransSalesCommission1'] + $v['currencyTransSalesCommission2'];
            $v['profit'] = $v['settleAmount'] - $v['currencyTransMchSettleAmount'] - $v['currencyTransSalesCommission'];

            $v['floatSettleAmount']                     = NumberUtils::centToYuan($v['settleAmount']);
            $v['floatServiceFeeRate']                   = NumberUtils::formatRate($v['serviceFeeRate']);
            $v['floatCurrencyTransMchSettleAmount']     = NumberUtils::centToYuan($v['currencyTransMchSettleAmount']);
            $v['floatCurrencyTransSalesCommission']     = NumberUtils::centToYuan($v['currencyTransSalesCommission']);
            $v['floatCurrencyTransSalesCommission1']    = NumberUtils::centToYuan($v['currencyTransSalesCommission1']);
            $v['floatCurrencyTransSalesCommission2']    = NumberUtils::centToYuan($v['currencyTransSalesCommission2']);
            $v['floatProfit']                           = NumberUtils::centToYuan($v['profit']);
            $list[$k] = $v;
        }
        $data = array(
            'total' => $total,
            'list' => $list
        );

        return CustomUtils::xeServiceReturnData(XZXResponseCode::SUCCESS_CODE,XZXResponseCode::getMessage(XZXResponseCode::SUCCESS_CODE),$data);
    }

    public function setChannelSettleAmount(array $param) {
        $info = $this->StatMonthlyChannelDao->get($param['id']);
        if (!$info) {
            throw new XZXValidationException(XZXResponseCode::getMessage(XZXResponseCode::DATA_NOT_FOUND));
        }
        $id = $param['id'];
        $data = [
            'settleAmount'  => $param['settleAmount']
        ];
        try {
            $this->StatMonthlyChannelDao->update($id, $data);
        } catch (\Throwable $th) {
            CustomUtils::xzxDebug($th->getMessage());
            throw new XZXValidationException(XZXResponseCode::getMessage(XZXResponseCode::EDIT_FAIL));
        }
        return CustomUtils::xeServiceReturnData(XZXResponseCode::SUCCESS_CODE,XZXResponseCode::getMessage(XZXResponseCode::SUCCESS_CODE),CustomUtils::xzxEmptyObject());
    }

    public function getTradeChannelList(array $param) {
        $limit = $param['limit'];
        $page = $param['page'];

        $total = $this->StatMonthlyTradeChannelDao->getCount($param);
        $list = $this->StatMonthlyTradeChannelDao->getList($param, $page, $limit);

        foreach ($list as $k => $v) {
            (isset($v['createTime']) && !empty($v['createTime'])) && $v['createTime'] = DateUtils::getDateTime($v['createTime']);
            $list[$k] = $v;
        }

        $data = array(
            'total' => $total,
            'list' => $list
        );
        return CustomUtils::xeServiceReturnData(XZXResponseCode::SUCCESS_CODE,XZXResponseCode::getMessage(XZXResponseCode::SUCCESS_CODE),$data);
    }

    /**
     * @param $param
     * @return array
     * 币种转换，并且进行损益计算
     */
    public function currencyTrans($param) {
        $data = $param['data'];

        $info = $this->StatMonthlyChannelDao->get($param['id']);
        if (!$info) {
            throw new XZXValidationException(XZXResponseCode::getMessage(XZXResponseCode::DATA_NOT_FOUND));
        }

        $id = $param['id'];
        $sumCurrencyTransSalesCommission1 = 0;
        $sumCurrencyTransSalesCommission2 = 0;
        $sumCurrencyTransMchSettleAmount = 0;

        Db::beginTransaction();
        try {

            foreach ($data as $value) {
                // 查询每条数据
                $tradeChannel = $this->StatMonthlyTradeChannelDao->get($value['id']);
                if (!$tradeChannel) {
                    throw new XZXValidationException(XZXResponseCode::getMessage(XZXResponseCode::DATA_NOT_FOUND));
                }

                // 根据汇率进行计算
                $currencyTransSalesCommission1 = $tradeChannel['salesCommission1'] == 0 ? 0 : $this->countCurrencyTransAmount($tradeChannel['salesCommission1'], $value['currencyTransRate']);
                $currencyTransSalesCommission2 = $tradeChannel['salesCommission2'] == 0 ? 0 : $this->countCurrencyTransAmount($tradeChannel['salesCommission2'], $value['currencyTransRate']);
                $currencyTransMchSettleAmount = $tradeChannel['settleAmount'] == 0 ? 0 : $this->countCurrencyTransAmount($tradeChannel['settleAmount'], $value['currencyTransRate']);

                $this->StatMonthlyTradeChannelDao->update($value['id'], [
                    'currencyTransRate'             => $value['currencyTransRate'],
                    'currencyTransSalesCommission1' => $currencyTransSalesCommission1,
                    'currencyTransSalesCommission2' => $currencyTransSalesCommission2,
                    'currencyTransMchSettleAmount'  => $currencyTransMchSettleAmount,
                ]);

                $sumCurrencyTransSalesCommission1 += $currencyTransSalesCommission1;
                $sumCurrencyTransSalesCommission2 += $currencyTransSalesCommission2;
                $sumCurrencyTransMchSettleAmount += $currencyTransMchSettleAmount;
            }

            // 更新渠道的转换金额
            $this->StatMonthlyChannelDao->update($id, [
                'currencyTransSalesCommission1' => $sumCurrencyTransSalesCommission1,
                'currencyTransSalesCommission2' => $sumCurrencyTransSalesCommission2,
                'currencyTransMchSettleAmount'  => $sumCurrencyTransMchSettleAmount,
            ]);

        } catch (\Throwable $th) {
            CustomUtils::xzxDebug($th->getMessage());
            Db::rollBack();
            throw new XZXValidationException(XZXResponseCode::getMessage(XZXResponseCode::EDIT_FAIL));
        }

        Db::commit();

        return CustomUtils::xeServiceReturnData(XZXResponseCode::SUCCESS_CODE,XZXResponseCode::getMessage(XZXResponseCode::SUCCESS_CODE), CustomUtils::xzxEmptyObject());
    }

    private function countCurrencyTransAmount($amount, $rate) {
        return round($rate / 1000000  * $amount);
    }

}
